﻿'Michael Khuyen
Imports System.Xml
Public Class DynamicMenu
    Private objXML As Xml.XmlDocument
    Public objForm As Object

    Public Function CreateMenuXML(ByRef menu As ToolStripMenuItem, ByVal PathElement As String, ByVal file As String) As ToolStripMenuItem
        
        objXML = New Xml.XmlDocument()
        objXML.Load(file)

        Dim objNode As Xml.XmlNode
        objNode = objXML.DocumentElement.SelectSingleNode("//" + PathElement)
        For Each objNode In objXML.FirstChild.ChildNodes
           
            Dim strmenu As New ToolStripMenuItem()
            strmenu.Name = objNode.Attributes.GetNamedItem("type").Value.Replace(" ", "")
            strmenu.Text = objNode.Attributes.GetNamedItem("type").Value
            strmenu.Tag = objNode.Attributes.GetNamedItem("type").Value.Replace(" ", "")
            'Dim strmenu_click As String = strmenu.Name + "_Click"
            ' AddHandler strmenu.Click, AddressOf strmenu.Name + "_Click"


            menu.DropDownItems.Add(strmenu)
            'If Not objNode.Attributes("OnClick") Is Nothing Then
            ' FindEventsByName(strmenu, objForm, True, strmenu.Name, "_Click")
            'End If
            For Each n As XmlNode In objNode.ChildNodes
                Dim sMenu1 As New ToolStripMenuItem()
                If (n.InnerText.Trim() <> "") Then
                    sMenu1.Text = n.InnerText
                    sMenu1.Name = n.InnerText.Replace(" ", "")
                Else
                    sMenu1.Text = n.Prefix
                    sMenu1.Name = n.Prefix.Replace(" ", "")
                End If
                
                FindEventsByName(sMenu1, objForm, True, sMenu1.Name, "_Click")
                strmenu.DropDownItems.Add(sMenu1)
            Next n
        Next
        Return menu
    End Function

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    'objective of this method is to find out the private event present in 

    'Form and attach the newly added menuitem to this event, this was 

    'achieved using Reflection technique

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    Private Sub FindEventsByName(ByVal sender As Object, _
     ByVal receiver As Object, ByVal bind As Boolean, _
     ByVal handlerPrefix As String, ByVal handlerSufix As String)
        ' Get the sender's public events.

        Dim SenderEvents() As System.Reflection.EventInfo = sender.GetType().GetEvents()
        ' Get the receiver's type and lookup its public

        ' methods matching the naming convention:

        '  handlerPrefix+Click+handlerSufix

        Dim ReceiverType As Type = receiver.GetType()
        Dim E As System.Reflection.EventInfo
        Dim Method As System.Reflection.MethodInfo
        For Each E In SenderEvents
            Method = ReceiverType.GetMethod( _
              handlerPrefix & E.Name & handlerSufix, _
              System.Reflection.BindingFlags.IgnoreCase Or _
              System.Reflection.BindingFlags.Instance Or _
              System.Reflection.BindingFlags.NonPublic)

            If Not Method Is Nothing Then
                Dim D As System.Delegate = _
                     System.Delegate.CreateDelegate(E.EventHandlerType, _
                                                    receiver, Method.Name)
                If bind Then
                    'add the event handler

                    E.AddEventHandler(sender, D)
                Else
                    'you can also remove the event handler if you pass bind

                    'variable as false

                    E.RemoveEventHandler(sender, D)
                End If
            End If
        Next
    End Sub

End Class
